﻿using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;

namespace Devonline.Identity;

/// <summary>
/// 实名认证信息, 字符主键的默认实现
/// 用户信息, 个人信息, 实名认证信息每个用户仅有一个, 第三方认证授权登录信息每个用户多个
/// 业务无关的用户认证信息, 用于和用户个人信息进行业务隔离
/// 一般情况下, 用户需要现在系统存在可登录的账户(user), 在进行实名认证
/// 在不存在系统账户的情况下, 可先从三方登录系统, 然后完成实名认证后, 根据认证资料自动创建可登录的系统账户
/// 实名认证信息, 需要在用户登录系统的情况下, 一步一步进行, 当第一步(手机号码认证)完成后, 即可创建实名认证数据, 身份证认证通过后, 将创建用户, 实名认证完成后创建个人信息
/// </summary>
[Table("real_name_info"), DisplayName("实名认证信息")]
public class RealNameInfo : RealNameInfo<string>, IIdentity, IEntitySet, IEntitySetWithCreate
{
    /// <summary>
    /// 用户信息, 用户信息和实名认证信息是一对一关系
    /// </summary>
    public virtual User User { get; set; } = null!;
    /// <summary>
    /// 通用附件集合, NotMapped Attachments 用于记录实体对象上上传的附件
    /// </summary>
    [NotMapped]
    public virtual ICollection<Attachment>? Attachments { get; set; }
}

/// <summary>
/// 实名认证信息
/// 用户信息, 个人信息, 实名认证信息每个用户仅有一个, 第三方认证授权登录信息每个用户多个
/// 业务无关的用户实名认证信息, 用于和用户个人信息进行业务隔离
/// 一般情况下, 用户需要现在系统存在可登录的账户(user), 在进行实名认证
/// 在不存在系统账户的情况下, 可先从三方登录系统, 然后完成实名认证后, 根据认证资料自动创建可登录的系统账户
/// 实名认证信息, 需要在用户登录系统的情况下, 一步一步进行, 当第一步(手机号码认证)完成后, 即可创建实名认证数据, 身份证认证通过后, 将创建用户, 实名认证完成后创建个人信息
/// </summary>
[Table("real_name_info"), DisplayName("实名认证信息")]
public abstract class RealNameInfo<TKey> : Identity<TKey>, IIdentity<TKey>, IEntitySet<TKey>, IEntitySetWithCreate<TKey> where TKey : IConvertible
{
    /// <summary>
    /// 用户编号
    /// </summary>
    [Column("user_id"), DisplayName("用户编号"), MaxLength(36), Excel]
    public virtual TKey? UserId { get; set; }

    #region 实名认证
    /// <summary>
    /// 是否已通过认证
    /// </summary>
    [Column("is_authed"), DisplayName("是否已认证"), Excel]
    public virtual bool IsAuthed { get; set; }
    /// <summary>
    /// 认证阶段
    /// </summary>
    [Column("auth_phase", TypeName = "varchar(16)"), DisplayName("认证阶段"), DefaultValue(AuthPhase.None), Excel]
    public virtual AuthPhase AuthPhase { get; set; } = AuthPhase.None;
    /// <summary>
    /// 身份证号码
    /// </summary>
    [ProtectedPersonalData]
    [Column("id_code"), DisplayName("身份证号码"), MaxLength(255), Excel]
    public virtual string? IdCode { get; set; }
    /// <summary>
    /// 联系方式
    /// </summary>
    [ProtectedPersonalData]
    [Column("phone_number"), MaxLength(255), DisplayName("手机号码"), Excel]
    public virtual string? PhoneNumber { get; set; }
    /// <summary>
    /// 验证码
    /// </summary>
    [Column("captcha"), MaxLength(16), DisplayName("验证码"), Excel]
    public virtual string? Captcha { get; set; }
    /// <summary>
    /// 验证码发送时间
    /// </summary>
    [Column("send_time"), DisplayName("验证码发送时间"), Excel]
    public virtual DateTime? SendTime { get; set; }
    /// <summary>
    /// 手机验证码验证时间, 记录最后一次验证码验证通过和不通过的时间
    /// </summary>
    [Column("validate_time"), DisplayName("验证码验证时间")]
    public virtual DateTime? ValidateTime { get; set; }
    /// <summary>
    /// 面部照片
    /// </summary>
    [Column("face_image"), MaxLength(128), DisplayName("面部照片"), Excel]
    public virtual string? FaceImage { get; set; }
    /// <summary>
    /// 认证视频
    /// </summary>
    [Column("auth_video"), MaxLength(128), DisplayName("认证视频"), Excel]
    public virtual string? AuthVideo { get; set; }
    /// <summary>
    /// 认证视频缩略图
    /// </summary>
    [Column("auth_video_thumbnail"), MaxLength(128), DisplayName("认证视频缩略图"), Excel]
    public virtual string? AuthVideoThumbnail { get; set; }
    /// <summary>
    /// 人脸匹配度得分
    /// </summary>
    [Column("face_match_score", TypeName = "decimal(8,4)"), DisplayName("人脸匹配度得分"), Excel]
    public virtual float? FaceMatchScore { get; set; }
    /// <summary>
    /// 微信小程序实名认证结果, 可供二次查询认证结果的访问地址
    /// </summary>
    [Column("verify_result"), MaxLength(255), DisplayName("实名认证结果"), Excel]
    public virtual string? VerifyResult { get; set; }
    #endregion

    #region 验证时间及次数
    /// <summary>
    /// 手机验证码验证时间, 记录最后一次验证码验证通过和不通过的时间
    /// </summary>
    [Column("phone_number_validate_time"), DisplayName("手机验证码验证时间"), Excel]
    public virtual DateTime? PhoneNumberValidateTime { get; set; }
    /// <summary>
    /// 身份证验证时间, 记录身份证验证通过和不通过的时间
    /// </summary>
    [Column("id_card_validate_time"), DisplayName("身份证验证时间"), Excel]
    public virtual DateTime? IdCardValidateTime { get; set; }
    /// <summary>
    /// 面部比对验证时间, 记录面部和身份证头像比对验证通过和不通过的时间
    /// </summary>
    [Column("face_compare_validate_time"), DisplayName("面部比对验证时间"), Excel]
    public virtual DateTime? FaceCompareValidateTime { get; set; }
    /// <summary>
    /// 面部活体识别验证时间, 记录面部活体识别验证通过和不通过的时间
    /// </summary>
    [Column("face_detection_validate_time"), DisplayName("面部活体识别验证时间"), Excel]
    public virtual DateTime? FaceDetectionValidateTime { get; set; }
    /// <summary>
    /// 手机验证码验证失败次数, 用于限制无限尝试
    /// </summary>
    [Column("phone_number_validate_failed_count"), DisplayName("手机验证码验证失败次数"), Excel]
    public virtual int PhoneNumberValidateFailedCount { get; set; }
    /// <summary>
    /// 身份证验证失败次数, 用于限制无限尝试
    /// </summary>
    [Column("id_card_validate_failed_count"), DisplayName("身份证验证失败次数"), Excel]
    public virtual int IdCardValidateFailedCount { get; set; }
    /// <summary>
    /// 面部比对验证失败次数, 用于限制无限尝试
    /// </summary>
    [Column("face_compare_validate_failed_count"), DisplayName("面部比对验证失败次数"), Excel]
    public virtual int FaceCompareValidateFailedCount { get; set; }
    /// <summary>
    /// 面部活体识别验证失败次数, 用于限制无限尝试
    /// </summary>
    [Column("face_detection_validate_failed_count"), DisplayName("面部识别验证失败次数"), Excel]
    public virtual int FaceDetectionValidateFailedCount { get; set; }
    #endregion
}
